/**
 * File Name	: DateTime.h
 * Location		: /Core/
 * Lib.Name		: Core.a
 * Designer		: OS (20-09-06)
 * Mod. 1 by	:
 */

#include "stdafx.h"
#include "CoreException.h"
#include "InternetAddress.h"
#include "System.h"
#include "Signal.h"
#ifdef WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#else
#include <unistd.h>
typedef socklen_t SOCKET;
#include <sys/time.h>
#endif

namespace Core
{

	void System::MilliSleep(double p_MilliSeconds)
	{
#ifdef WIN32
		Sleep(p_MilliSeconds);
#else
		usleep(p_MilliSeconds*1000);
#endif
	}

	bool System::IsFDReady(int p_FD, FDTypes p_FDtype, int p_TimeOutMilliSeconds)
	{
		if(p_TimeOutMilliSeconds>=0)
		{
		    fd_set t_FD;
			struct timeval t_TV;
			int t_Retval;
			FD_ZERO(&t_FD);
			FD_SET(p_FD, &t_FD);
			t_TV.tv_sec = p_TimeOutMilliSeconds/1000;
			t_TV.tv_usec = (p_TimeOutMilliSeconds%1000)*1000;
			if(p_FDtype==FDType_Read)
			{
				t_Retval = select(p_FD+1, &t_FD, NULL, NULL, &t_TV);
			}
			else if(p_FDtype==FDType_Write)
			{
				t_Retval = select(p_FD+1, NULL, &t_FD, NULL, &t_TV);
			}
			else if(p_FDtype==FDType_Except)
			{
				t_Retval = select(p_FD+1, NULL, NULL, &t_FD, &t_TV);
			}
			else
			{
				return false;
			}
			if(t_Retval==-1)
			{
				throw CoreException();
			}
			else if(t_Retval==0)
			{
				return false;
			}
		}
		return true;
	}

	int System::Execute(std::string p_Path, std::string p_Command)
	{
#ifdef WIN32
		STARTUPINFO t_SI;
		PROCESS_INFORMATION t_PI;
		LPTSTR t_Command = _tcsdup(p_Command.c_str());
		ZeroMemory(&t_SI, sizeof(STARTUPINFO));
		t_SI.cb = sizeof(STARTUPINFO);
		ZeroMemory(&t_PI, sizeof(PROCESS_INFORMATION));
		CreateProcess(NULL, t_Command, NULL, NULL, false, 0, NULL, NULL, & t_SI, &t_PI);
		return t_PI.dwProcessId;
#else
		int t_Pid = fork();
		if(t_Pid==0)
		{
			setsid();
			execl(p_Path.c_str(), p_Command.c_str(), (char*)0);
		}
		else if(t_Pid>0)
		{
			return t_Pid;
		}
		return -1;
#endif
	}

	bool System::IsExecuted(int p_Pid)
	{
#ifdef WIN32
		DWORD t_ExitStatus;
		HANDLE t_Handle = OpenProcess(0x1F0FFF, false, p_Pid);
		return ((t_Handle!=NULL) && GetExitCodeProcess(t_Handle, &t_ExitStatus) && (t_ExitStatus==259));
#else
		return false;
#endif
	}

	int System::SendSignal(int p_Pid, int p_Signal)
	{
#ifdef WIN32
		return 0;
#else
		return kill(p_Pid, p_Signal);
#endif
	}

	void System::Terminate(int p_Pid)
	{
		if(p_Pid==0) return;
#ifdef WIN32
		TerminateProcess(OpenProcess(0x1F0FFF, false, p_Pid), 1);
#else
		kill(p_Pid, 9);
#endif
	}

	std::string System::GetEnv(std::string p_Env)
	{
#ifdef WIN32
		return "";
#else
		return getenv(p_Env.c_str());
#endif
	}

	InternetAddress System::GetPeerName(int p_SD)
	{
		sockaddr_in t_SockAddrIn;
	#ifdef WIN32
		int t_SinSize = sizeof(sockaddr_in);
	#else
		SOCKET t_SinSize = sizeof(sockaddr_in);
	#endif
		getpeername(p_SD, (sockaddr*) &t_SockAddrIn, &t_SinSize);
		InternetAddress t_InternetAddress;
		t_InternetAddress.SetSockAddrIn(t_SockAddrIn);
		return t_InternetAddress;
	}

	std::string System::ToRadixString(unsigned long p_Integer, unsigned char p_Radix)
	{
		char t_Char[16];
#ifdef WIN32
		_itoa_s((int)p_Integer, t_Char, 16, p_Radix);
#else
		sprintf(t_Char, "%d", (int)p_Integer);
#endif
		return t_Char;
	}

	std::string System::ToTimeString(unsigned long p_Seconds)
	{
		std::ostringstream t_String;
		unsigned long t_Long;
		p_Seconds %= 86400;
		t_Long = p_Seconds/3600;
		if(t_Long<10) t_String << "0";
		t_String << t_Long;
		t_String << ":";
		p_Seconds %= 3600;
		t_Long = p_Seconds/60;
		if(t_Long<10) t_String << "0";
		t_String << t_Long;
		t_String << ":";
		p_Seconds %= 60;
		t_Long = p_Seconds;
		if(t_Long<10) t_String << "0";
		t_String << t_Long;
		return t_String.str();
	}

}
